package trim.common.sm;

import java.util.ArrayList;
import java.util.List;
import trim.common.inputdata.FormatOrder;
import trim.common.result.Pattern;
import trim.common.result.PatternItem;
import trim.common.result.TrimResult;

/**
 * TrimSimplex.java
 * Реализация СМ с дополнительными функциями специфичными для ЗФР
 * Для начальных данных использует интерфейс {@link ITrimSMData}.
 * Created on 12.11.2008 21:50:38
 * @author Дмитрий
 */
public class TrimSimplex extends Simplex
{

  public TrimSimplex(ITrimSMData smData)
  {
    super(smData);
  }

  /**
   * Получение целой части решения СМ
   * @return целая часть решения СМ
   */
  public TrimResult getTrimResult()
  {
    List<FormatOrder> vt=getSmData().getFormatCountList();
    double X[][]=getBaseMatrix();
    double res[]=getObjectiveFunction();
    int n=getSmData().getProblemSize();
    TrimResult tr=new TrimResult();
    //int []b=new int[n];
    for(int i=0;i<n;i++)
    {
      int x=(int)Math.floor(res[i]+2e-10);
      if(x==0)
        continue;
      //b[i]=0;
      Pattern p=new Pattern();
      p.setCount(x);
      for(int j=0;j<n;j++)
      {
        if(vt.get(j).getFormat().getLength()!=0)
          p.add(new PatternItem(vt.get(j).getFormat()),(int)X[j][i]);
      }
      p.setMaterial(getSmData().getMatrialCountList().get(0).getMaterial());
      tr.add(p);
    }
    return tr;
  }

  /**
   * Выделение остатка вектора требований.
   * @return остаток вектора требований
   */
  public List<FormatOrder> getRestFormatCount()
  {
    List<FormatOrder> vt=getSmData().getFormatCountList();
    double X[][]=getBaseMatrix();
    double res[]=getObjectiveFunction();
    int n=getSmData().getProblemSize();
    List<FormatOrder> lfc=new ArrayList(n);
    int[] b=new int[n];
    for(int i=0;i<n;i++)
      b[i]=vt.get(i).getCount();
    for(int i=0;i<n;i++)
    {
      int x=(int)Math.floor(res[i]+2e-10);
      //b[i]=0;

      Pattern p=new Pattern();
      p.setCount(x);
      for(int j=0;j<n;j++)
        b[j]-=(int)X[j][i]*x;
    }
    for(int i=0;i<n;i++)
      lfc.add(new FormatOrder(vt.get(i).getFormat(),b[i]));
    return lfc;
  }

  /**
   * Расчетное количество оставшихся единиц сырья
   * @return
   */
  public int getRestMaterials()
  {

    TrimResult tr=getTrimResult();
    return (int)roundObjectiveFunction()-tr.getUsedMaterialsCount();
  }

  public double roundObjectiveFunction()
  {
    double f=getObjectiveFunctionValue();
    if(f-Math.floor(f+1e-11)<1e-9)
      f=Math.floor(f+1e-11);
    else
      f=Math.floor(f+1e-11)+1;
    return f;
  }

  @Override
  public ITrimSMData getSmData()
  {
    return (ITrimSMData)super.getSmData();
  }
}
